home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Experimental BBS Explossion 3
/
Experimental BBS Explossion III.iso
/
pascal
/
xlibpas.zip
/
XLIB.DOC
< prev
next >
Wrap
Text File
|
1993-10-24
|
58KB
|
1,512 lines
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ XLIB - Graphics Library for Borland/Turbo Pascal v6.0/7.0 ║
║ ║
╠═══════════════════════════════════════════════════════════════════════════╣
║ ║
║ Original code by ║
║ ║
║ Themie Gouthas - egg@dstos3.dsto.gov.au ║
║ ║
║ Some of the code in this library has been contributed by : ║
║ ║
║ Matthew MacKenzie - matm@eng.umd.edu ║
║ ║
║ I informally reserve all rights to the code in XLIB ║
║ Rights to contributed code is also assumed to be reserved by ║
║ the original authors. ║
║ ║
╠═══════════════════════════════════════════════════════════════════════════╣
║ ║
║ Conversion to Borland/Turbo Pascal v6.0/7.0 by ║
║ ║
║ Tristan Tarrant - tristant@cogs.susx.ac.uk ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
╔═══════════════════════════════════════════════════════════════════════════╗
║ DISCLAIMER ║
╚═══════════════════════════════════════════════════════════════════════════╝
This library is distributed AS IS. The author/s specifically disclaim any
responsibility for any loss of profit or any incidental, consequential or
other damages.
╔═══════════════════════════════════════════════════════════════════════════╗
║ INTRODUCTION ║
╚═══════════════════════════════════════════════════════════════════════════╝
XLIB is a "user supported freeware" graphics library specifically designed
with game programming in mind.
It has been placed in the public domain for the benefit of all, and
represents *MANY* hours of work so it is requested that all users comply
with the the wishes of the author/s as specified in the individual modules
and:
a) To leave the code in the public domain
b) Not distribute any modified or incomplete versions of this library
New contribution and comments are welcome and hopefully there will be more
releases as the code evolves.
Finally, do not trust this excuse for a manual if in doubt, as this code has
undergone several revisions. The place to get the answers is in the code
itself.
╔═══════════════════════════════════════════════════════════════════════════╗
║ REQUIREMENTS ║
╚═══════════════════════════════════════════════════════════════════════════╝
Minimum requirements
286 processor,
VGA,
Borland/Turbo Pascal v6.0/7.0
╔═══════════════════════════════════════════════════════════════════════════╗
║ GENERAL FEATURES ║
╚═══════════════════════════════════════════════════════════════════════════╝
Support for a number of 256 colour tweaked graphics mode resolutions
320x200 320x240 360x200 360x240 376x282 320x400 320x480 360x400 360x480
360x360 376x308 376x564
Please note that some of the new resolutions best suit monitors with
adjustable vertical height.
Virtual screens larger than the physical screen (memory permitting) that
can be panned at pixel resolution in all directions
A split screen capability for status displays etc.
Text functions supporting 8x8 and 8x14 ROM fonts and user defined fonts
Support for page flipping
Graphics primitives such as line and rectangle drawing functions and
of course bit block manipulation functions
╔═══════════════════════════════════════════════════════════════════════════╗
║ BUILDING THE LIBRARIES ║
╚═══════════════════════════════════════════════════════════════════════════╝
To compile XLIB just load it in the IDE and press F9. If you prefer the
command line compiler then just run TPC xlib.
╔═══════════════════════════════════════════════════════════════════════════╗
║ USING THE LIBARY WITH YOUR PROGRAMS ║
╚═══════════════════════════════════════════════════════════════════════════╝
Using the XLIB library in your programs is simple. Just include the XLIB
unit in the uses statement at the beginning of your program which will make
all the procedures and functions composing the XLIB library available.
╔═══════════════════════════════════════════════════════════════════════════╗
║ GLOBAL CONSTANTS AND VARIABLES ║
╚═══════════════════════════════════════════════════════════════════════════╝
Available X mode resolutions :
XMODE320x200 = 0
XMODE320x240 = 1
XMODE360x200 = 2
XMODE360x240 = 3
XMODE360x282 = 4
XMODE320x400 = 5
XMODE320x480 = 6
XMODE360x400 = 7
XMODE360x480 = 8
XMODE360x360 = 9
XMODE376x308 = 10
XMODE376x564 = 11
Palette rotation direction direction :
RBackward = 0
RForward = 1
Error constants :
XModeInvalid = -1
Error = 1
OK = 0
InGraphics : byte - Flag indicating that the xlib graphics system is
active. Set by function "xsetmode".
CurrXMode : word - If the xlib graphics system is active, contains the id
of the x mode. Set by function "xsetmode".
See also constants (i.e. XMODE320x200 ... )
ScrnPhysicalByteWidth : word - Physical screen width in bytes. Set by
function "xsetmode"
ScrnPhysicalPixelWidth - word - Physical screen width in pixels. Set by
function "xsetmode"
ScrnPhysicalHeight : word - Physical screen height in pixels. Set by
function "xsetmode".
ErrorValue : word - Contains error value. General use variable to
communicate the error status from several functions. The value
in this variable usually is only valid for the the last
function called that sets it.
SplitScrnOffs : word - Offset in video ram of split screen. Set by
function "xsetsplitscrn". The value is only valid if a split
screen is active. See also global variable "SplitScrnActive".
SplitScrnScanLine : word - Screen Scan Line the Split Screen starts at
initially when set by function "xsetsplitscrn". The value is only
valid if a split screen is active. See also global variable
"SplitScrnActive".This variable is not updated by "xhidesplitscrn",
"xadjustsplitscrn".
SplitScrnVisibleHeight : word - The number of rows of the initial split
screen which are currently displayed. Modified by "xhidesplitscrn",
"xadjustsplitscrn" and "xshowsplitscrn".
Page0Offs : word - Offset in video ram of main virtual screen. Initially
set by function "xsetmode" but is updated by functions
"xsetsplitscrn" and "xsetdoublebuffer".
Page1Offs : word - Offset in video ram of second virtual screen. Set by
and only is valid after a call to "xsetdoublebuffer".
ScrnLogicalByteWidth : word - Virtual screen width in bytes. Set by
function "xsetmode".
ScrnLogicalPixelWidth : word - Virtual screen width in pixels. Set
by function "xsetmode".
ScrnLogicalHeight : word - Virtual screen height in pixels. Set
initially by function "xsetmode" but is updated by functions
"xsetsplitscrn" and "xsetdoublebuffer".
MaxScrollX : word - Max X pixel position of physical screen within
virtual screen. Set by function "xsetmode".
MaxScrollY : word - Max Y position of physical screen within virtual
screen. Set initially by function "xsetmode" but is updated by
functions "xsetsplitscrn" and "xsetdoublebuffer".
DoubleBufferActive : word - Indicates whether double-buffering is on. Set
by function "xsetdoublebuffer".
VisiblePageIdx : word - Index number of current visible page. Initially
set by function "xsetdoublebuffer" but is updated by "xpageflip".
This variable is only used while double buffering is on.
HiddenPageOffs : word - Offset of hidden page. Initially set by function
"xsetdoublebuffer" but is updated by "xpageflip". This variable
is only used while double buffering is on.
VisiblePageOffs : word - Offset of visible page. Initially set by function
"xsetdoublebuffer" but is updated by "xpageflip". This variable
is only used while double buffering is on.
NonVisualOffs : word - Offset of first byte of non-visual ram, the ram
that is available for bitmap storage etc. Set initially by function
"xsetmode" but is updated by functions "xsetsplitscrn" and
"xsetdoublebuffer".
TopClip, BottomClip, LeftClip, RightClip : word - Define the clipping
rectangle for Linear and Video clipped bitmap put functions. Set
either manually or by "xsetcliprect". Note X coordinates are in
bytes as all clip functions clip to byte boundaries.
PhysicalStartPixelX : word - X pixel Offset of physical (visible) screen
relative to the upper left hand corner (0,0) of the virtual screen.
PhysicalStartByteX : word - X byte Offset of physical (visible) screen
relative to the upper left hand corner (0,0) of the virtual screen.
PhysicalStartY : word - Y pixel Offset of physical (visible) screen
relative to the upper left hand corner (0,0) of the virtual screen.
╔═══════════════════════════════════════════════════════════════════════════╗
║ EXPORTED PROCEDURES AND FUNCTIONS ║
╚═══════════════════════════════════════════════════════════════════════════╝
xsetmode
--------
Function XSetMode( mode, WidthInPixels : word ) : word;
mode - The required mode as defined by the "Available X Mode
resolutions" set of defines in the xlib.h header file.
WidthInPixels - The required virtual screen width.
Returns - The actual width in pixels of the allocated virtual
screen
This function initialises the graphics system, setting the apropriate
screen resolution and allocating a virtual screen. The virtual screen
allocated may not necessarily be of the same size as specified in the
"WidthInPixels" parameter as it is rounded down to the nearest
multiple of 4.
The function returns the actual width of the allocated virtual screen
in pixels if a valid mode was selected otherwise returns
XMODEINVALID.
Saves virtual screen pixel width in "ScrnLogicalPixelWidth".
Saves virtual screen byte width in "ScrnLogicalByteWidth".
Physical screen dimensions are set in "ScrnPhysicalPixelWidth".
"ScrnPhysicalByteWidth" and "ScrnPhysicalHeight". Other global variables
set are "CurrXMode","MaxScrollX", "MaxScrollY", "InGraphics".
The variable "SplitScrnScanline" is also initialized to zero.
See also:
Available X Mode resolutions
What is Mode X
xselectdefaultplane
-------------------
Procedure XSelectDefaultPlane( plane : byte );
Enables default Read/Write access to a specified plane
xsetsplitscreen
-----------------
Procedure XSetSplitScreen( line : word );
line - The starting scan line of the required split screen.
This function activates Mode X split screen and sets starting scan line
The split screen resides on the bottom half of the screen and has a
starting address of A000:0000 in video RAM.
It also Updates Page0Offs to reflect the existence of the split screen
region ie "MainScrnOffset" is set to the offset of the first pixel
beyond the split screen region. Other variable set are "Page1Offs" which
is set to the same value as "Page0Offs" (see graphics call sequence below),
"ScrnLogicalHeight","ScrnPhysicalHeight", "SplitScrnScanLine" and
"MaxScrollY".
This function cannot be called after double buffering has been activated,
it will return an error. To configure your graphics environment the
sequence of graphics calls is as follows although either or both steps b
and c may be omitted:
a) xsetmode
b) xsetsplitscreen
c) xsetdoublebuffer
Thus when you call this function successfully, double buffering is not
active so "Page1Offs" is set to the same address as "Page0Offs".
WARNING: If you use one of the high resolution modes (376x564 as an
extreme example) you may not have enough video ram for split screen
and double buffering options since VGA video RAM is restricted to
64K.
See Also:
What is a Split Screen ?
What is double buffering ?
xsetdoublebuffer
----------------
Function xsetdoublebuffer( PageHeight : word ) : word;
PageHeight - The height of the two double buffering virtual screens.
Returns - The closest possible height to the specified.
This function sets up two double buffering virtual pages. "ErrorValue"
is set according to the success or failure of this command.
Other variables set are:
Page1Offs - Offset of second virtual page
NonVisualOffs - Offset of first non visible video ram byte
DoubleBufferActive - Flag
PageAddrTable - Table of Double buffering pages start offsets
ScrnLogicalHeight - Logical height of the double buffering pages
MaxScrollY - Max vertical start address of physical screen
within the virtual screen
WARNING: If you use one of the high resolution modes (376x564 as an
extreme example) you may not have enough video ram for split screen
and double buffering options since VGA video RAM is restricted to 64K.
See Also:
What is double buffering ?
xhidesplitscreen
----------------
Procedure XHideSplitScreen;
This function hides an existing split screen by setting its starting
scan line to the last physical screen scan line.
"ScreenPhysicalHeight" is adjusted but the "SplitScreenScanLine" is not
altered as it is required for restoring the split screen at a later stage.
WARNING: Only to be used if SplitScrnLine has been previously called
Disabled for mode 5-11 (320x400-376x564). The memory for
the initial split screen is reserved and the size limitations
of these modes means any change in the split screen scan line
will encroach on the split screen ram
Update: Now disabled for these modes
See Also:
What is a split screen ?
xshowsplitscreen
----------------
Procedure XShowSplitScreen;
Restores split screen start scan line to the initial split screen
starting scan line as set by "SplitScrnScanLine".
"ScreenPhysicalHeight" is adjusted.
WARNING: Only to be used if SplitScrnLine has been previously called
Disabled for mode 4-10 (320x400-376x564). The memory for
the initial split screen is reserved and the size limitations
of these modes means any change in the split screen scan line
will encroach on the split screen ram
XAdjustSplitScreen
------------------
Procedure XAdjustSplitScreen( line : word );
line - The scan line at which the split screen is to start.
Sets the split screen start scan line to a new scan line. Valid scan lines
are between the initial split screen starting scan line and the last
physical screen scan line. "ScreenPhysicalHeight" is also adjusted.
WARNING: Only to be used if SplitScrnLine has been previously called
Disabled for mode 4-10 (320x400-376x564). The memory for
the initial split screen is reserved and the size limitations
of these modes means any change in the split screen scan line
will encroach on the split screen ram
XSetStartAddr
-------------
Procedure XSetStartAddr( X, Y : word );
X,Y - coordinates of top left corner of physical screen within current
virtual screen.
Set Mode X non split screen physical start address within current virtual
page.
X must not exceed (Logical screen width - Physical screen width)
ie "MaxScrollX" and Y must not exceed (Logical screen height -
Physical screen height) ie "MaxScrollY"
XPageFlip
---------
Procedure XPageFlip( X, Y : word );
X,Y - coordinates of top left corner of physical screen within the
the hidden virtual screen if double buffering is active, or
the current virtual screen otherwise.
Sets the physical screen start address within currently hidden virtual
page and then flips pages. If double buffering is not active then this
function is functionally equivalent to "xsetstartaddr".
X must not exceed (Logical screen width - Physical screen width)
ie "MaxScrollX" and Y must not exceed (Logical screen height -
Physical screen height) ie "MaxScrollY"
xtextmode
---------
Procedure xtextmode;
Disables graphics mode.
xsetcliprect
------------
Procedure xsetcliprect( left, top, right, bottom : word );
Defines the clipping rectangle for clipping versions of planar and video
bitmap puts.
NOTE: Compiled bitmaps cannot be clipped.
xputpix
-------
Procedure xputpix( X, Y, PageOffset, Color : word );
Draw a point of specified colour at coordinates X,Y
within the virtual page starting at offset PageOffset.
xgetpix
---------
Function xgetpix( X, Y, PageBase : word ) : word;
Read a point of at coordinates X,Y within the virtual page starting
at offset PageOffset.
xrectpattern
------------
Procedure xrectpattern( StartX, StartY,
EndX, EndY, PageBase : word;
var Pattern );
StartX,StartY - Coordinates of upper left hand corner of rectangle
EndX,EndY - Coordinates of lower right hand corner of rectangle
PageBase - Offset of virtual screen
*Pattern - Pointer to the user defined pattern (16 bytes)
Mode X rectangle 4x4 pattern fill routine.
Upper left corner of pattern is always aligned to a multiple-of-4
row and column. Works on all VGAs. Uses approach of copying the
pattern to off-screen display memory, then loading the latches with
the pattern for each scan line and filling each scan line four
pixels at a time. Fills up to but not including the column at EndX
and the row at EndY. No clipping is performed.
Based on code originally published in DDJ Mag by M. Abrash
Warning the VGA memory locations PATTERNBUFFER (A000:FFFc) to
A000:FFFF are reserved for the pattern buffer
See Also:
Doctor Dobbs Journal references.
xrectpatternclipped
-------------------
As above but clipped.
xcpvidrect
----------
Procedure xcpvidrect( SourceStartX, SourceStartY,
SourceEndX, SourceEndY,
DestStartX, DestStartY,
SourcePageBase, DestPageBase,
SourceBitmapWidth, DestBitmapWidth : word );
StartX,StartY- Coordinates of upper left hand corner of source rectangle
EndX,EndY - Coordinates of lower right hand corner of source rectangle
DestStartX,DestStartY - Coordinates of rectangle destination
SourcePageBase - source rectangle page offset
DestPageBase - destination rectangles page offset
SourceBitmapWidth - width of bitmap within the source virtual screen
containing the source rectangle
DestBitmapWidth - width of bitmap within the dest. virtual screen
containing the destination rectangle
Mode X display memory to display memory copy
routine. Left edge of source rectangle modulo 4 must equal left edge
of destination rectangle modulo 4. Works on all VGAs. Uses approach
of reading 4 pixels at a time from the source into the latches, then
writing the latches to the destination. Copies up to but not
including the column at SrcEndX and the row at SrcEndY. No
clipping is performed. Results are not guaranteed if the source and
destination overlap.
Based on code originally published in DDJ Mag by M. Abrash
See Also:
Doctor Dobbs Journal references.
xshiftrect
----------
Procedure xshiftrect ( SrcLeft, SrcTop, SrcRight, SrcBottom,
DestLeft, DestTop, ScreenOffs : word );
SrcLeft, SrcTop - Coordinates of upper left hand corner of rectangle
SrcRight, SrcBottom - Coordinates of lower right hand corner of rectangle
DestLeft, DestTop - Coordinates of upper left corner of destination
ScreenOffs - Offset of virtual screen
This function copies a rectangle of VRAM onto another area of VRAM,
even if the destination overlaps with the source. It is designed
for scrolling text up and down, and for moving large areas of screens
around in tiling systems. It rounds all horizontal coordinates to
the nearest byte (4-column chunk) for the sake of speed. This means
that it can NOT perform smooth horizontal scrolling. For that,
either scroll the whole screen (minus the split screen), or copy
smaller areas through system memory using the functions in the
XPBITMAP module.
SrcRight is rounded up, and the left edges are rounded down, to
ensure that the pixels pointed to by the arguments are inside the
the rectangle. That is, SrcRight is treated as (SrcRight+3) >> 2,
and SrcLeft as SrcLeft >> 2.
The width of the rectangle in bytes (width in pixels / 4)
cannot exceed 255.
╔═══════════════════════════════════════════════════════════════════════════╗
║ Palette functions for VGA 256 color modes ║
╚═══════════════════════════════════════════════════════════════════════════╝
All the functions in this module operate on two variations of the
palette buffer, the raw and annotated buffers.
All those functions ending in "raw" operate on the following palette
structure:
r0,g0,b0,r1,g1,b1,...rn,gn,bn : byte;
No reference to the starting colour index or number of colours stored
is contained in the structure.
All those functions ending in "struc" operate on the following palette
structure:
c, n, r0,g0,b0,r1,g1,b1,...rn,gn,bn : byte;
where c is the starting colour and n is the number of colours stored
WARNING : There is no validity checking in these functions. The onus is
on the user to supply valid parameters to the functions.
xgetpalraw
----------
Procedure xgetpalraw( var pal; numcolrs, startindex : word );
Read DAC palette into raw buffer with interrupts disabled
WARNING: Memory for the palette buffers must all be pre-allocated.
xgetpalstruc
------------
Procedure xgetpalstruc( var pal, numcolrs, startindex : word );
Read DAC palette into annotated type buffer with interrupts disabled
WARNING: memory for the palette buffers must all be pre-allocated
xputpalraw
----------
Procedure xputpalraw( var pal; numcolrs, startindex : word );
Write DAC palette from raw buffer with interrupts disabled
xputpalstruc
------------
Procedure xputpalstruc( var pal );
Write DAC palette from annotated type buffer with interrupts disabled
xsetrgb
-------
Procedure xsetrgb( color, redc, greenc, bluec : byte );
Set the RGB components of a vga color
xrotpalstruc
------------
Procedure xrotpalstruc( var pal; direction : word );
Rotate annotated palette buffer entries.
Direction 0 = backward, 1 = forward.
xrotpalraw
----------
Procedure xrotpalraw( var pal; direction, numcolrs : word );
Rotate a raw palette buffer.
Direction 0 = backward, 1 = forward.
xputcontrastpalstruc
--------------------
Procedure xputcontrastpalstruc( var pal; intensity : byte );
Write DAC palette from annotated type buffer with specified intensity
adjustment (ie palette entries are decremented where possible by
"intensity" units).
Designed for fading in or out a palette without using an intermediate
working palette buffer ! (Slow but memory efficient ... OK for small
pal strucs)
xtransposepalstruc
------------------
Procedure xtransposepalstruc( var pal; StartColor : word );
Write DAC palette from annotated type buffer with interrupts disabled
starting at a new palette index.
xcpcontrastpalstruc
-------------------
Function xcpcontrastpalstruc( var srcpal, destpal; Intensity : byte );
Copy one annotated palette buffer to another making the intensity
adjustment. Used in fading in and out fast and smoothly.
xline
-----
Procedure xline( x0, y0, x1, y1, color, PageBase : word );
Draw a line with the specified end points in the page starting at
offset "PageBase".
No Clipping is performed.
╔═══════════════════════════════════════════════════════════════════════════╗
║ FONTS ║
╚═══════════════════════════════════════════════════════════════════════════╝
FONT8x8 = 0
FONT8x15 = 1
FONTUSER = 2
EXPORTED VARIABLES
NOTE: All variables are read only. I you modify them the results may
be unpredictable.
CharHeight - byte - Height of current inbuilt character set
CharWidth - byte - Width of current inbuilt character set
FirstChar - byte - First character of current inbuilt character set
UserCharHeight - byte - Height of current user character set
UserCharWidth - byte - Width of current user character set
UserFirstCh - byte - First character of current user character set
xtextinit
---------
Procedure xtextinit;
Initializes the Mode X text driver and sets the default font (VGA ROM 8x8)
xsetfont
--------
Procedure xsetfont( FontId : word );
Select the working font where 0 = VGA ROM 8x8, 1 = VGA ROM 8x14
2 = User defined bitmapped font.
WARNING: A user font must be registered before setting FontID 2
See Also:
Font constants.
xregisteruserfont
-----------------
Procedure xregisteruserfont( var UserFontPtr );
Register a user font for later selection. Only one user font can be
registered at any given time. Registering a user font deregisters the
previous user font. User fonts may be at most 8 pixels wide.
USER FONT STRUCTURE
Word: ascii code of first char in font
Byte: Height of chars in font
Byte: Width of chars in font
n*h*Byte: the font data where n = number of chars and h = height
of chars
WARNING: The onus is on the program to ensure that all characters
drawn whilst this font is active, are within the range of
characters defined.
xputchar
--------
Function xputchar( ch : char; X, Y, PgOffs, Color : word ) : word;
Draw a text character at the specified location with the specified
color.
ch - char to draw
x,y - screen coords at which to draw ch
ScrnOffs - Starting offset of page on whih to draw
Color - Color of the text
Returns the width of the character.
WARNING: InitText must be called before using this function
xprintf
-------
Procedure xprintf( x, y, ScrnOffs, color : word; s : string );
x,y - screen coords at which to draw ch
ScrnOffs - Starting offset of page on whih to draw
Color - Color of the text
s - Text to be displayed
xbgprintf
---------
Procedure xbgprintf( x, y, ScrnOffs, fgcolor, bgcolor : word; s: string );
x,y - screen coords at which to draw ch
ScrnOffs - Starting offset of page on whih to draw
fgcolor - Color of the text foreground
bgcolor - Color of the text background
s - String to be displayed
xgetcharwidth
-------------
Function xgetcharwidth( ch :char ) : word;
ch - character to get width of
╔═══════════════════════════════════════════════════════════════════════════╗
║ PLANAR BITMAPS ║
╚═══════════════════════════════════════════════════════════════════════════╝
Planar bitmaps as used by these functions have the following structure:
byte 0 The bitmap width in bytes (4 pixel groups) range 1..255
byte 1 The bitmap height in rows range 1..255
byte 2..n1 The plane 0 pixels width*height bytes
byte n1..n2 The plane 1 pixels width*height bytes
byte n2..n3 The plane 2 pixels width*height bytes
byte n3..n4 The plane 3 pixels width*height bytes
These functions provide the fastest possible bitmap blts from system ram
to video and further, the single bitmap is applicable to all pixel
alignments. The masked functions do not need separate masks since all non
zero pixels are considered to be masking pixels, hence if a pixel is 0 the
corresponding screen destination pixel is left unchanged.
xputmaskedpbm
-------------
Procedure xputmaskedpbm( X, Y, ScrnOffs : word; var Bitmap );
Mask write a planar bitmap from system ram to video ram. All zero source
bitmap bytes indicate destination byte to be left unchanged.
Source Bitmap structure:
Width, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
Bitmap data (plane 2)..,Bitmap data (plane 3)..
NOTE: width is in bytes ie lots of 4 pixels
LIMITATIONS: No clipping is supported
Only supports bitmaps with widths which are a multiple of
4 pixels
See BITMAP TOOLS for linear <-> planar bitmap conversion
functions.
xputpbm
-------
Procedure xputpbm( X, Y, ScrnOffs : word; var Bitmap );
Write a planar bitmap from system ram to video ram.
Source Bitmap structure:
Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
Bitmap data (plane 2)..,Bitmap data (plane 3)..
NOTE: width is in bytes ie lots of 4 pixels
LIMITATIONS: No clipping is supported
Only supports bitmaps with widths which are a multiple of
4 pixels
See BITMAP TOOLS for linear <-> planar bitmap conversion
functions.
xgetpbm
-------
Procedure xgetpbm( X, Y : word; Bw, Bh : byte;
ScrnOffs : word; var Bitmap );
Read a planar bitmap to system ram from video ram.
Source Bitmap structure:
Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
Bitmap data (plane 2)..,Bitmap data (plane 3)..
NOTE: width is in bytes ie lots of 4 pixels
LIMITATIONS: No clipping is supported
Only supports bitmaps with widths which are a multiple of
4 pixels
╔═══════════════════════════════════════════════════════════════════════════╗
║ CLIPPED PLANAR BITMAPS ║
╚═══════════════════════════════════════════════════════════════════════════╝
There are three variations of the previous procedures identified by the
three function name extensions: clipx, clipy clipxy.
Because speed is critical in games programming you do not want to be
checking for clipping if not necessary thus for sprites that move only
horizontally you would use the clipx version of the put function,
for sprites that move vertically you would use the clipy version and for
sprites that move both directions you would use the clipxy version.
Keep in mind also that the clipping components of these functions assume
that the clipping rectangle is equal to or larger than the size of the
bitmap ie. if a bitmap is top clipped, it is assumed that the bitmap's
bottom is not also clipped. Similarly with horizontal clipping.
Note: performance in decreasing order is as follows :
clipy,clipx,clipxy with masked puts being slower than unmasked
puts
Horizontal clipping is performed to byte boundaries (4 pixels) rather than
pixels. This allows for the fastest implementation of the functions. It is
not such a handicap because for one, your screen width a multiple of 4
pixels wide and for most purposes it is the screen edges that form the
clipping rectangle.
Following is an example of setting a clipping rectangle to the logical
screen edges:
xsetcliprect(0,0,ScrnLogicalByteWidth,ScrnLogicalHeight)
xputpbmclipx
------------
xputpbmclipy
------------
xputpbmclipxy
-------------
xputmaskedpbmclipx
------------------
xputmaskedpbmclipy
------------------
xputmaskedpbmclipxy
-------------------
For a detailed description of parameters etc. see equivalent PLANAR
BITMAP procedures
╔═══════════════════════════════════════════════════════════════════════════╗
║ COMPILED BITMAPS ║
╚═══════════════════════════════════════════════════════════════════════════╝
The Care and Feeding of Compiled Masked Blits
by Matthew MacKenzie
The procedures are dedicated to compiled bitmaps :
o xcompilebitmap compiles your bitmap into native code which writes
to the VGA screen in an X mode.
o xputcbitmap converts X and Y coordinates into a location on the
screen, sets up the necessary VGA registers, and executes the compiled
bitmap as a subroutine.
o xsizeofcbitmap takes a planar bitmap and returns an integer equal to
the size of the compiled bitmap which the planar bitmap would produce.
It is essentially a lobotomized version of xcompilebitmap, with all
the code generation replaced with a size counter.
Xcompilebitmap scans through a source bitmap and generates 8086
instructions to plot every nonzero pixel. It is designed to be used
before the action begins rather than on-the-fly. The compiled bitmap
contains no branches, and no reference to the zero (transparent) pixels.
Where two pixels are exactly four columns apart they are plotted with a
single 16-bit store, and the VGA MAPMASK register will be set at most
four times. As a result your bitmap may run several times faster than a
traditional memory-to-VGA masked blit routine.
There is no way to perform clipping on these bitmaps, or to plot a
pixel of color zero.
Xcompilebitmap works with bitmaps in the standard Xlib planar bitmap
format. On a time scale of 60 frames per second, it is actually relatively
slow. Since a compiled bitmap is relocatable you may just want to have it
saved to disk, and not include the source bitmap in your program at all.
The source bitmap format is an array of bytes, a little like this:
eye : array[0..29] of byte =
( 4, 7, { four byte columns across, seven rows tall }
0, 0, 0, 0, 9, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0,
0, 0, 9, 9, 1, 1, 1, 4, 4, 9, 9, 0, 0, 0, 0, 0,
0, 9, 9, 1, 2, 0, 0, 4, 4, 1, 9, 9, 0, 0, 0, 0,
9, 9, 9, 1, 0, 0, 0, 0, 1, 1, 9, 9, 9, 0, 0, 0,
0, 9, 9, 1, 2, 0, 0, 2, 1, 1, 9, 9, 0, 0, 0, 0,
0, 0, 9, 9, 1, 1, 1, 1, 1, 9, 9, 0, 0, 0, 0, 0,
0, 0, 0, 0, 9, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0 );
This is actually a linear bitmap, which is the wrong format for
compilation, but is easier on human eyes. Use the BITMAP TOOLS procedures
to convert linear bitmaps into planar bitmaps, and vice-versa.
To compile this image for a mode 360 pixels (90 byte columns) across:
planareye : array[0..29] of byte;
EyeSize : word;
CompiledEye : pointer;
xbmtopbm( eye, planareye);
EyeSize := xsizeofcbitmap(planareye);
GetMem(CompiledEye, EyeSize);
xcompilebitmap(90, planareye, CompiledEye^);
Notice that both buffers must exist beforehand. Since xcompilebitmap
returns the size of the compiled code, in bytes, you can reallocate the
bitmap immediately to the right size if using xsizeofxbitmap seems
inconvenient (reallocation may even be faster, though using the function is
cleaner). The pointers are 32-bit because compiled bitmaps take so much
space: they are at one end of the speed-versus-memory spectrum. A good
rule of thumb is to allocate (3.5 x buffer-height x buffer-width) + 25
bytes (rounding up ;-), then pare your bitmap down when you find out how
much space you've actually used.
Since the compiled bitmap has to fit within one segment of memory, it
cannot contain more than about 19,000 pixels. This will not be a
limitation for most sane programmers. If you are not a sane programmer try
splitting your huge, unwieldy image up into smaller parts -- you can use
the same gigantic bitmap if you divide it into horizontal slices for
compilation. For that matter, dividing the source up that way will let
you use a source bitmap large than 64K, which is an even sicker idea...
Back to business. A bitmap is compiled for only one width of screen.
If you are using a logical screen larger than your physical screen, call
the bitmap compiler with the logical width -- the important thing is the
number of bytes per line. Notice that you do not have to be in a graphics
mode to use this routine. This allows you to develop and compile bitmaps
separately, with whatever utility programs you might cook up.
The final function is xputcbitmap. To plot our eye at (99,4), on
the page which starts at location 0:
xputcbitmap(99, 4, 0, CompiledEye);
This function depends on the global variable ScrnLogicalByteWidth from
the module XMAIN, which should be the same number as the column parameter
you used to compile your bitmap.
The XCBITMAP module supports memory-to-VGA blits only. Xlib also
includes non-masking routines which can quickly save and restore the
background screen behind your bitmap, using fast string operations.
This module is part of the Xlib package, and is in the public domain.
If you write something which uses it, though, please send me a copy as a
courtesy -- if for no other reason so I can tilt my chair back and reflect
that it may have been worth the trouble after all.
The included program DEMO2.C demonstrates the performance difference
between planar bitmap masked blits and compiled bitmap blits.
xcompilepbm
-----------
xsizeofcpbm
-----------
Identical to the previous ones, but they work on PBMs
╔═══════════════════════════════════════════════════════════════════════════╗
║ VIDEO BITMAPS ║
╚═══════════════════════════════════════════════════════════════════════════╝
The VIDEO BITMAPS procedures implement yet another type of bitmap to
complement planar and compiled bitmaps, VRAM based bitmaps. If a 4 cylinder
car is analagous to planar bitmaps, that is thrifty on memory consumption but
low performance and and a V8 is analagous to Compiled bitmaps, memory guzzlers
that really fly, then VRAM based bitmaps are the 6 cylinder modest performers
with acceptable memory consumption.
To summarise their selling points, VBM's are moderately fast with fair memory
consumption, and unlike compiled bitmaps, can be clipped. The disadvantages
are that they are limited by the amount of free video ram and have a complex
structure.
The VRAM bitmap format is rather complex consisting of components stored in
video ram and components in system ram working together. This complexity
necessitates the existence of a creation function "xmakevbm" which takes
an input linear bitmap and generates the equivalent VBM (VRAM Bit Map).
VBM structure:
word 0 Size Total size of this VBM structure in bytes
word 1 ImageWidth Width in bytes of the image (for all alignments)
word 2 ImageHeight Height in scan lines of the image
word 3 Alignment 0 ImagePtr Offset in VidRAM of this aligned image
+--word 4 MaskPtr Offset (within this structure's DS) of
| . alignment masks
| .
| .
| word 9 Alignment 3 ImagePtr Offset in VidRAM of this aligned image
+|--word 10 MaskPtr Offset (within this structure's DS) of
|| alignment masks
||
|+->byte 21 (word 11) -------+-- Image masks for alignment 0
| . |
| . |
| byte 21 + ImageWidth*ImageHeight -----+
|
| .
| . (similaly for alignments 1 - 2 )
| .
|
+-->byte 21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3
. |
. |
byte 21 + 4*(ImageWidth*ImageHeight) --+
.
.
<< Similarly for alignments 2 and 3 >>
.
.
byte 21 + 4*(ImageWidth*ImageHeight)
-------------
(And dont forget the corresponding data in video ram)
You can see for yourself the complexity of this bitmap format. The image
is stored in video ram in its 4 different alignments with pointers to these
alignments in the VBM. Similarly there are 4 alignments of the corresponding
masks within the VBM itself (towards the end). The mask bytes contain the
plane settings for the corresponding video bytes so that one memory move can
move up to 4 pixels at a time (depending on the mask settings) using the
VGA's latches, theoretically giving you a 4x speed improvement over
conventional blits like the ones implemented in "XPBITMAP". In actual fact
its anywhere between 2 and 3 due to incurred overheads.
These bitmaps are more difficult to store in files than PBM'S and CBM's but
still posible with a bit of work, so do not dismiss these as too difficult
to use. Consider all the bitmap formats carefully before deciding on which
to use. There may even be situations that a careful application of all three
types would be most effective ie. compiled bitmaps for Background tiles and
the main game character (which never need clipping), VRAM based bitmaps for
the most frequently occuring (oponent, alien etc) characters which get
clipped as they come into and leave your current location and planar bitmaps
for smaller or less frequently encountered characters.
xmakevbm
--------
Function xmakevbm( var lbm; var VramStart : word ) : pointer;
Create the VBM from the given linear bitmap and place the image alignments
in video ram starting at the offset in the variable pointed to by
"VramStart". "VramStart" is then updated to point to the next free VRAM byte
(just after the last byte of the image alignments). Usually you will point
"VramStart" to "NonVisualOffs".
lbm Pointer to the input linear bitmap
VramStart Pointer to variable containing Offset of first free VRAM byte
xputmaskedvbm
-------------
C Prototype: extern int xputmaskedvbm(int X, int Y, word ScrnOffs,
byte far * VBitmap);
Draw a VRAM based bitmap at (X,Y) relative to the screen with starting
offset "ScrnOffs".
Returns 1 if clipped image is fully clipped (ie no portion of it
appears on the screen) otherwise it returns 0
xputmaskedvbmclipx
------------------
xputmaskedvbmclipy
------------------
xputmaskedvbmclipxy
-------------------
Clipping versions of "xputmaskedvbm".
╔═══════════════════════════════════════════════════════════════════════════╗
║ MOUSE ROUTINES ║
╚═══════════════════════════════════════════════════════════════════════════╝
These procedures implement very basic mouse handling functions. The way
in which they operate is by installing an event handler function during
initialization which subsequently intercepts and processes mouse events and
automatically updates status variables such as mouse position and button
pressed status. It does not support the full functionality of:
SPLIT SCREENS
SCROLLED WINDOWS
VIRTUAL WINDOWS
This was done to primarily prevent unecessary impedences to performance,
since the mouse handler function has the potential to degrade performance.
It also saves me alot of coding which I was too lazy to do.
Programs communicate with the mouse driver as with other devices, through
an interrupt vector namely 33h. On generating an interrupt, the mouse driver
expects a function number in AX and possibly other parameters in other
registers and returns information via the registers. A brief description
of the mouse functions follows:
--------------------------------------
MS Mouse Driver Functions
Mouse Initialization 0
Show Cursor 1
Hide Cursor 2
Get Mouse Position & Button Status 3
Set Mouse Cursor Position 4
Get Button Press Information 5
Get Button Release Information 6
Set Min/Max Horizontal Position 7
Set Min/Max Vertical Position 8
Define Graphics Cursor Block 9
Define Text Cursor 10
Read Mouse Motion Counters 11
Define Event Handler 12
Light Pen Emulation Mode ON 13
Light Pen Emulation Mode OFF 14
Set Mouse Mickey/Pixel Ratio 15
Conditional Hide Cursor 16
Set Double-Speed Threshold 19
--------------------------------------
In practice only afew of these functions are used and even fewer when the
mouse status is monitored by an event handler function such as is used in
this module.
The most important thing to note when using the mouse module is that the
mouse event handler must be removed before exiting the program. It is a good
idea to have an exit function and include the line "xmouseremove" along with
any other pre-exit cleanup code.
EXPORTED VARIABLES
MouseInstalled - word - Indicates whether mouse handler installed
MouseHidden - word - Indicates whether mouse cursor is hidden
MouseButtonStatus - word - Holds the mouse button status
MouseX - word - Current X position of mouse cursor
MouseY - word - Current Y position of mouse cursor
MouseFrozen - word - Disallows position updates if TRUE
MouseColor - byte - The mouse cursors colour
xmouseinit
----------
Procedure xmouseinit;
Initialize the mouse driver functions and install the mouse event handler
function. This is the first function you must call before using any of the
mouse functions. This mouse code uses the fastest possible techniques to
save and restore mouse backgrounds and to draw the mouse cursor.
WARNING: This function uses and updates "NonVisualOffset" to allocate
video ram for the saved mouse background.
LIMITATIONS: No clipping is supported horizontally for the mouse cursor
No validity checking is performed for NonVisualOffs
**WARNING** You must Hide or at least Freeze the mouse cursor while drawing
using any of the other XLIB procedures since the mouse handler may
modify vga register settings at any time. VGA register settings
are not preserved which will result in unpredictable drawing
behavior. If you know the drawing will occur away from the
mouse cursor set MouseFrozen to TRUE (1), do your drawing
then set it to FALSE (0). Alternatively call "xhidemouse",
perform your drawing and then call "xshowmouse". Another
alternative is to disable interrupts while drawing but usually
drawing takes up alot of time and having interrupts disabled
for too long is not a good idea.
xdefinemousecursor
------------------
Procedure xdefinemousecursor( var MouseDef; MouseColor : byte );
MouseDef - a pointer to 14 characters containing a bitmask for all the
cursor's rows.
MouseColor - The colour to use when drawing the mouse cursor.
Define a mouse cursor shape for use in subsequent cursor redraws. XMouse
has a hardwired mouse cursor size of 8 pixels across by 14 pixels down.
WARNING: This function assumes MouseDef points to 14 bytes.
Note: Bit order is in reverse. ie bit 7 represents pixel 0 ..
bit 0 represents pixel 7 in each "MouseDef" byte.
xshowmouse
----------
Procedure xshowmouse;
Makes the cursor visible if it was previously hidden.
See Also: "xhidemouse".
xhidemouse
----------
Procedure xhidemouse;
Makes the cursor hidden if it was previously visible.
See Also: "xshowmouse".
xmouseremove
------------
Procedure xmouseremove;
Stop mouse event handling and remove the mouse handler.
NOTE: This function MUST be called before quitting the program if
a mouse handler has been installed
xpositionmouse
--------------
Procedure xpositionmouse( x,y : integer );
Positions the mouse cursor at the specified location
xmousewindow
------------
Procedure xmousewindow( x0, y0, x1, y1 : integer );
Defines a mouse window.
xupdatemouse
------------
Procedure xupdatemouse;
Forces the mouse position to be updated and cursor to be redrawn.
Note: this function is useful when you have set "MouseFrozen" to true.
Allows the cursor position to be updated manually rather than
automatically by the installed handler.
╔═══════════════════════════════════════════════════════════════════════════╗
║ BITMAP TOOLS ║
╚═══════════════════════════════════════════════════════════════════════════╝
xpbmtobm
--------
Procedure xpbmtobm( var sourcepbm, destbm );
This function converts a bitmap in the planar format to the linear format
as used by xcompilebitmap.
WARNING: the source and destination bitmaps must be pre - allocated
NOTE: This function can only convert planar bitmaps that are suitable.
If the source planar bitmap's width (per plane) is >= 256/4
it cannot be converted.
xbmtopbm
--------
Procedure xbmtopbm( var sourcepbm, destbm );
This function converts a bitmap in the linear format as used by
xcompilebitmap to the planar formap.
WARNING: the source and destination bitmaps must be pre - allocated
NOTE: This function can only convert linear bitmaps that are suitable.
If the source linear bitmap's width is not a multiple of 4
it cannot be converted.
╔═══════════════════════════════════════════════════════════════════════════╗
║ CIRCLE ROUTINES ║
╚═══════════════════════════════════════════════════════════════════════════╝
Wheel Have to See About That
by Matthew MacKenzie
The circle procedures are :
o xcircle, oddly enough, draws a circle.
o xfilledcircle does too, only the circle is filled (in some
libraries this is called a disc).
The word `circle' here refers to a round thing which is as many
pixels tall as across. It only looks like a circle in 320x240 mode --
the original mode X -- and in 376x282 mode.
In both procedures, the circle is specified by the coordinates of the
upper-left-hand corner of the smallest box which holds it, and the
diameter. Some circle functions have you specify a center point;
this system is kind of odd because a circle with an even diameter does
not have a particular pixel for a center. Every circle, on the other
hand, has a box with an upper-left corner.
No bounds are checked. A diameter of zero will draw nothing, and
a negative diameter will blow your VGA board into hundreds of thousands
of tiny little smoldering fragments. Neither function supports clipping.
The calculation of the circle is based on an algorithm described
by Michael P. Lindner in a letter to the editor on page 8 of Dr. Dobb's
Journal #169 (October 1990). The algorithm has been rearranged to
allow drawing and moving the plots in the eight octants to be performed
in one step, so that each pixel does not have to be loaded into the CPU
twice. xfilledcircle does not take advantage of this optimization
because it handles different parts of each plot at different times.
xcircle
------
Procedure xcircle ( Left, Top, Diameter, Color, ScreenOffs : word );
Draws a circle with the given upper-left-hand corner and diameter,
which are given in pixels.
xfilledcircle
-------------
Procedure xfilledcircle( Left, Top, Diameter, Color, ScreenOffs : word );
Draws a filled circle with the given upper-left-hand corner and
diameter.
╔═══════════════════════════════════════════════════════════════════════════╗
║ POLYGON ROUTINES ║
╚═══════════════════════════════════════════════════════════════════════════╝
xtriangle
---------
Procedure xtriangle( x0, y0, x1, y1, x2, y2, color, PageBase : word );
This procedure draws a filled triangle which is clipped to the current
clipping window defined by TopClip,BottomClip,LeftClip,RightClip.
Remember: the X clipping variable are in byteS not PIXELS so you
can only clip to 4 pixel byte boundaries.
xpolygon
--------
Procedure xpolygon( var vertices; numvertices, color, PageBase : word );
This procedure is similar to the triangle function but draws
convex polygons. The vertices are supplied in the form of a FAR
pointer.
NOTE: a convex polygon is one such that if you draw a line from
any two vertices, every point on that line will be within the
polygon.
This procedure works by splitting up a polygon into its component
triangles and calling the triangle routine above to draw each one.
Performance is respectable but a custom polygon routine might be
faster.
╔═══════════════════════════════════════════════════════════════════════════╗
║ REFERENCE SECTION ║
╚═══════════════════════════════════════════════════════════════════════════╝
In my opinion Doctor Dobbs Journal is the best reference text for
VGA Mode X graphics:
Issue 178 Jul 1991 : First reference to Mode X
Article Abstract : VGA's undocumented Mode X supports page flipping,
makes off screen memory available, has square pixels,
and increases performance by as muck as 4 times.
Issue 179 Aug 1991 : Continuation
Article Abstract : Michael discusses latches and VGA's undoccumented
Mode X.
Issue 181 Sep 1991 : Continuation
Article Abstract : Michael puts the moves on animation using VGA's 256
colors.
Issue 184 Oct 1991 : First of a continuing series covering 3-D animation
using VGA's Mode X. This series is still ongoing
(October 1992)
Article Abstract : Michael moves into 3-D animation, starting with basic
polygon fills and page flips.
WHAT IS MODE X ?
----------------
Mode X is a derivative of the VGA's standard mode 13h (320x200 256 color).
It is a (family) of undocumented video modes that are created by tweaking
the VGA's registers. The beauty of mode X is that it offers several
benefits to the programmer:
- Multiple graphice pages where mode 13h doesn't allowing for page flipping
(also known as double buffering) and storage of images and data in
offscreen video memory
- A planar video ram organization which although more difficult to program,
allows the VGA's plane-oriented hardware to be used to process pixels in
parallel, improving performance by up to 4 times over mode 13h
See issue 178-179 of D.D.J. for a full description of VGA's Mode X.
WHAT IS A SPLIT SCREEN ?
------------------------
A split screen is a neat hardware feature offered by the EGA and VGA video
cards. A split screen is a mode of graphics operationin which the Hardware
splits the visual graphics screen horizontally and treats both halves as
individual screens each starting at different locations in video RAM.
The bottom half (which is usually referred to as the split screen) always
starts at address A000:0000 but the top half's starting address is user
definable.
The most common application of split screens in games is the status display
in scrolling games. Split screens make this sort of game simpler to program
because when the top half window is scrolled the programmer does not have to
worry about redrawing the bottom half.
WHAT IS DOUBLE BUFFERING ?
--------------------------
Double buffering (also known as page flipping) is the technique most often
used to do animation. it requires hardware that is capable of displaying
multiple graphics pages (or at least 2). Animation is achieved by drawing
an image in the non visible screen and then displaying the non visible
screen. Once the page has been flipped the process starts again. The next
frame of the animation is drawn on the non visible screen, the page is
flipped again etc.
WHAT IS TRIPLE BUFFERING ?
--------------------------
Triple buffering is similar to double buffering in many ways, but it
relies on 3 pages being defined for animation. The main selling point
of triple buffering is that it eliminates the need to wait for the
vertical retrace to flip pages before drawing on the new page thus
alowing the programmer to start building the next animation frame
immediately after completing the current one. Heres how it works:
With double buffering, once you complete drawing the hidden page and
youre ready to flip pages, you have to wait for the VGA hardware to
actually flip the page (during the vertical retrace) before you start
drawing the next page otherwise you will be drawing on the visible page.
With triple buffering you cycle between three pages, thus the page you
draw on is guaranteed not to be visible. I know this is a poor
description but it really is quite simple
Triple buffering can acheive the fastest possible animation under the
right conditions but the draw back is that more video RAM is required. If
you wish to store bitmaps in video ram such as background tiles, double
buffering would be the better alternative.